import Moya
import SwiftUI

enum API {
    case appleIdLogin(code: String)
    case userInfo
    case categoryList
    case shopList(name: String?, firstLevel: Int?, secondLevel: Int?, lon: String?, lat: String?, pageNum: Int, pageSize: Int)
    case foodDetail(id: Int)
    case shopDetail(id: Int)
    case shopEvaluationList(id: String)
    case addShopEvaluation
    case likeShop
    case foodList(storeId: Int, pageSize: Int, pageNum: Int)
}

extension API: TargetType {
    var baseURL: URL {
        return URL(string: "http://makandong.com/prod-api")!
    }

    var path: String {
        switch self {
        case .appleIdLogin:
            return "/loginAppleId"
        case .userInfo:
            return "/getApiInfo"
        case .categoryList:
            return "/homePage/category"
        case .shopList:
            return "/homePage/merchant"
        case .foodDetail:
            return "/homePage/goodsById"
        case .shopDetail:
            return "/homePage/merchantById"
        case .shopEvaluationList:
            return "/homePage/evaluate"
        case .addShopEvaluation:
            return "/homePage/evaluateAdd"
        case .likeShop:
            return "/homePage/like"
        case .foodList:
            return "/homePage/goodsList"
        }
    }

    var method: Moya.Method {
        switch self {
        case .appleIdLogin, .addShopEvaluation, .likeShop:
            return .post
        case .userInfo, .categoryList, .shopList, .foodDetail, .shopDetail, .shopEvaluationList, .foodList:
            return .get
        }
    }

    var task: Task {
        switch self {
        case let .appleIdLogin(code):
            return .requestParameters(parameters: ["code": code], encoding: JSONEncoding.default)
        case .userInfo, .categoryList:
            return .requestPlain
        case let .shopList(name, firstLevel, secondLevel, lon, lat, pageNum, pageSize):
            var parames: [String: Any] = [
                "pageNum": pageNum,
                "pageSize": pageSize
            ]
            parames["name"] = name
            parames["firstLevel"] = firstLevel
            parames["secondLevel"] = secondLevel
            parames["lon"] = lon
            parames["lat"] = lat
            return .requestParameters(parameters: parames, encoding: URLEncoding.default)
        case .foodDetail(let id):
            return .requestParameters(parameters: ["id": id], encoding: URLEncoding.default)
        case .shopDetail(let id):
            return .requestParameters(parameters: ["id": id], encoding: URLEncoding.default)
        case .shopEvaluationList(let id):
            return .requestParameters(parameters: ["id": id], encoding: URLEncoding.default)
        case .addShopEvaluation:
            return .requestParameters(parameters: [:], encoding: JSONEncoding.default)
        case .likeShop:
            return .requestParameters(parameters: [:], encoding: JSONEncoding.default)
        case let .foodList(storeId, pageSize, pageNum):
            var parames: [String: Any] = [
                "pageNum": pageNum,
                "pageSize": pageSize,
                "merchantId": storeId
            ]
            return .requestParameters(parameters: parames, encoding: URLEncoding.default)
        }
    }

    var headers: [String: String]? {
        var headerDic = ["Content-Type": "application/json"]
        switch self {
        case .appleIdLogin:
            break
        default:
            let defaultNcd = NcdDefaults()
            headerDic["Authorization"] = "Bearer \(defaultNcd.userToken)"
        }
        return headerDic
    }
}


/// 网络错误枚举
enum NetworkError: BaseError {
    case decodingFailed
    case moyaError(String)
    case service(String)
    case invalidToken
    case noNetwork
    
    var message: String {
        switch self {
        case .decodingFailed:
            return "数据解析失败"
        case .moyaError(let message):
            return message
        case .service(let msg):
            return msg
        case .invalidToken:
            return "无效token"
        case .noNetwork:
            return "无网路连接"
        }
    }
}

/// Moya 网络管理器
class NetworkManager {
    static let shared = NetworkManager()
    
    private let provider = MoyaProvider<API>(session: Session(configuration: {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30 // 请求超时时间
        configuration.timeoutIntervalForResource = 30 // 资源超时时间
        return configuration
    }()))
    
    private init() {}
    
    /// 通用请求方法，支持 async/await
    func request<T: Decodable>(_ target: API, responseType: T.Type) async throws -> T {
        return try await withCheckedThrowingContinuation { continuation in
            provider.request(target) { result in
                switch result {
                case .success(let response):
                    do {
                        let filteredResponse = try response.filterSuccessfulStatusCodes()
                        let decoder = JSONDecoder()
                        let model = try decoder.decode(BaseResponseModel.self, from: filteredResponse.data)
                        switch model.code {
                        case 200:
                            let data = try decoder.decode(T.self, from: filteredResponse.data)
                            continuation.resume(returning: data)
                        case 401:
                            continuation.resume(throwing: NetworkError.invalidToken)
                        default:
                            continuation.resume(throwing: NetworkError.service(model.msg))
                        }
                    } catch {
                        Log.error(error)
                        continuation.resume(throwing: NetworkError.decodingFailed)
                    }
                case .failure(let error):
                    continuation.resume(throwing: NetworkError.moyaError(error.localizedDescription))
                }
            }
        }
    }
}

class BaseResponseModel: Codable {
    let code: Int
    let msg: String
}
